﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Drawing;
using System.Drawing.Design;
using System.Windows.Forms;
using pF.DesignSurfaceExt;
using XMLFT;


namespace FormDesigner
{
    public partial class DesignForm : Form
    {
        private List<IDesignSurfaceExt2> _listOfDesignSurface = new List<IDesignSurfaceExt2>();

        private IDesignSurfaceExt2 GetCurrentIDesignSurface()
        {
            if (null == this._listOfDesignSurface) return null;
            if (0 == this._listOfDesignSurface.Count) return null;

            return _listOfDesignSurface[this.tabControl1.SelectedIndex];
        }

        // Will hold all the buttons you can select to CREATE controls.
        private List<ToolStripItem> efStripButtons = new List<ToolStripItem>();

        private List<string> allowedExtendableControls = new List<string>();

        public DesignForm()
        {
            InitializeComponent();

            allowedExtendableControls.Add("System.Windows.Forms.TextBox");
            allowedExtendableControls.Add("System.Windows.Forms.ComboBox");
            allowedExtendableControls.Add("System.Windows.Forms.CheckBox");
            allowedExtendableControls.Add("SATBox.SATextBox");

            //- Add the toolboxItems to the future toolbox 
            //- the pointer
            ToolboxItem toolPointer = new System.Drawing.Design.ToolboxItem();
            toolPointer.DisplayName = "<Pointer>";
            toolPointer.Bitmap = new System.Drawing.Bitmap(16, 16);
            listBox1.Items.Add(toolPointer);
            //- the control
            listBox1.Items.Add(new ToolboxItem(typeof(TextBox)));
            listBox1.Items.Add(new ToolboxItem(typeof(Label)));
            listBox1.Items.Add(new ToolboxItem(typeof(CheckBox)));
            listBox1.Items.Add(new ToolboxItem(typeof(ComboBox)));
            listBox1.Items.Add(new ToolboxItem(typeof(SATBox.SATextBox)));

            resetExtendedPropControls();
        }

        #region Main Form Events

        private void DesignerForm_Load(object sender, EventArgs e)
        {
            this.tabControl1.Selected += new System.Windows.Forms.TabControlEventHandler(this.OnTabPageSelected);

            //- select into the property grid the current Form 
            SelectRootComponent();
        }

        private void OnTabPageSelected(object sender, TabControlEventArgs e)
        {
            //- select into the property grid the current Form 
            SelectRootComponent();
        }

        private void DesignForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (MessageBox.Show("Are you sure you want to exit?", "Exit?", MessageBoxButtons.YesNo) == DialogResult.Yes)
            {
                // TODO : As program is designed, need to do cleanup here.
            }
            else { e.Cancel = true; }
        }

        #endregion    
    
        #region Menu Functions

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            buildXMLFile();
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (tabControl1.TabCount == 0)
            {
                MessageBox.Show("You need to create a work area first from File->New Work Area.", "No Work Area?");
                return;
            }
            if (MessageBox.Show("Clear Form Box and load new Form from file system?", "Clear?", MessageBoxButtons.YesNo) == DialogResult.No)
            {
                return;
            }

            // Create an instance of the open file dialog box.
            OpenFileDialog openFileDialog1 = new OpenFileDialog();

            // Set filter options and filter index.
            openFileDialog1.Filter = "XML (.xml)|*.xml";
            openFileDialog1.FilterIndex = 1;
            openFileDialog1.InitialDirectory = Application.StartupPath;

            openFileDialog1.Multiselect = true;

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                Control gbFileTemplate = null;
                IDesignSurfaceExt isurf = GetCurrentIDesignSurface();

                if (null != isurf)
                    gbFileTemplate = (Control)isurf.GetIDesignerHost().RootComponent;
                else
                    return;

                do
                {
                    foreach (Control child in gbFileTemplate.Controls)
                    {
                        gbFileTemplate.Controls.Remove(child);
                        child.Parent = null;
                        child.Dispose();
                    }
                } while (gbFileTemplate.Controls.Count > 0);

                gbFileTemplate.Controls.Clear();
                gbFileTemplate.Update();

                LoadXMLTemplateDesign((openFileDialog1.FileName), isurf);
            }

        }

        #endregion    
    
        #region Helper Functions for Control Events

        private void resetExtendedPropControls()
        {
            panelXMLExtendedTagProps.Enabled = false;

            tbExtendedPropText.Text = "";
            tbExtendedPropOutlookID.Text = "";
            nudExtentedPropPosition.Value = 0;
            cbExtendedPropRequired.Checked = false;
            tbExtendedPropRequires.Text = "";

            panelXMLExtendedTagProps.Enabled = true;
        }

        private void buildXMLFile()
        {
            Control workingControl = null;
            IDesignSurfaceExt isurf = GetCurrentIDesignSurface();
            if (null != isurf)
                workingControl = (Control)isurf.GetIDesignerHost().RootComponent;

            if (workingControl.Controls.Count == 0)
            {
                MessageBox.Show("No Controls in the Group Box to export!");
                return;
            }

            XMLFormTemplate thisTemplate = new XMLFormTemplate();

            thisTemplate.AddAll(workingControl);

            thisTemplate.SaveXMLTemplate();
            // FIXME : Need to add an AddToFormList() function that allows you to select list file and add this to the list.
        }

        #endregion

        #region Toolstrip Functions
/*
        private void tsbFormListEditor_Click(object sender, EventArgs e)
        {
            ListEditorForm _editorBox = new ListEditorForm();
            if (_editorBox.IsDisposed)
                _editorBox = new ListEditorForm();
            else
                _editorBox.Focus();
            _editorBox.TopMost = true;
            _editorBox.Show();
        }
*/
        private void tsbSaveForm_Click(object sender, EventArgs e)
        {
            buildXMLFile();
        }

        private void tsbResetForm_Click(object sender, EventArgs e)
        {
            resetBuildForm();
        }

        private void resetBuildForm()
        {
            if (MessageBox.Show("Clear Form Design And Start Over?", "Clear?", MessageBoxButtons.YesNo) == DialogResult.No)
            {
                return;
            }

            Control workingControl = null;
            IDesignSurfaceExt isurf = GetCurrentIDesignSurface();
            if (null != isurf)
                workingControl = (Control)isurf.GetIDesignerHost().RootComponent;
            else
                return;

            do
            {
                foreach (Control child in workingControl.Controls)
                {
                    workingControl.Controls.Remove(child);
                    child.Parent = null;
                    child.Dispose();
                }
            } while (workingControl.Controls.Count > 0);

            workingControl.Controls.Clear();
            workingControl.Update();
        }

        #endregion

        #region Design Surface System

        private void EditMenuItem_Click(object sender, EventArgs e)
        {
            IDesignSurfaceExt isurf = GetCurrentIDesignSurface();
            if (null != isurf)
                isurf.DoAction((sender as ToolStripMenuItem).Text);
        }

        private void newFormUseSnapLinesMenuItem_Click(object sender, EventArgs e)
        {
            TabPage tp = new TabPage("Design Form (SnapLines)");
            this.tabControl1.TabPages.Add(tp);
            int iTabPageSelectedIndex = this.tabControl1.SelectedIndex;
            //- steps.1.2.3
            DesignSurfaceExt2 surface = CreateDesignSurface();
            //- step.4
            //- choose an alignment mode...
            ((DesignSurfaceExt2)surface).UseSnapLines();
            //- step.5
            //- create the Root compoment, in these cases a Form
            try
            {
                Form rootComponent = null;
                rootComponent = (Form)surface.CreateRootComponent(typeof(Form), new Size(800, 620));
                rootComponent.Text = "Root Component (800x620)";
                rootComponent.BackColor = Color.Yellow;
                //-
                //-
                //- step.4
                //- display the DesignSurface
                Control view = surface.GetView();
                if (null == view)
                    return;
                //- change some properties
                view.Text = "Test Form N. " + iTabPageSelectedIndex;
                view.Dock = DockStyle.Fill;
                //- Note these assignments
                view.Parent = tp;
                //- finally enable the Drag&Drop on RootComponent
                ((DesignSurfaceExt2)surface).EnableDragandDrop();
            }//end_try
            catch (Exception ex)
            {
                MessageBox.Show(Name + " the DesignSurface N. " + iTabPageSelectedIndex + " has generated errors during loading!Exception: " + ex.Message);
                return;
            }//end_catch
        }

        private void newFormUseGridandSnapMenuItem_Click(object sender, EventArgs e)
        {
            TabPage tp = new TabPage("Design Form (Snap To Grid)");
            this.tabControl1.TabPages.Add(tp);
            int iTabPageSelectedIndex = this.tabControl1.SelectedIndex;
            //- steps.1.2.3
            DesignSurfaceExt2 surface = CreateDesignSurface();
            //- step.4
            //- choose an alignment mode...
            ((DesignSurfaceExt2)surface).UseGrid(new System.Drawing.Size(32, 32));
            //- step.5
            //- create the Root component, in these cases a Form
            try
            {
                Form rootComponent = null;
                rootComponent = (Form)surface.CreateRootComponent(typeof(Form), new Size(800, 620));
                rootComponent.Text = "Root Component (800x620)";
                rootComponent.BackColor = Color.YellowGreen;
                //-
                //-
                //- step.4
                //- display the DesignSurface
                Control view = surface.GetView();
                if (null == view)
                    return;
                //- change some properties
                view.Text = "Test Form N. " + iTabPageSelectedIndex;
                view.Dock = DockStyle.Fill;
                //- Note these assignments
                view.Parent = tp;
            }//end_try
            catch (Exception ex)
            {
                MessageBox.Show(Name + " the DesignSurface N. " + iTabPageSelectedIndex + " has generated errors during loading!Exception: " + ex.Message);
                return;
            }//end_catch
        }

        private void newFormUseGridMenuItem_Click(object sender, EventArgs e)
        {
            TabPage tp = new TabPage("Design Form (Grid)");
            this.tabControl1.TabPages.Add(tp);
            int iTabPageSelectedIndex = this.tabControl1.SelectedIndex;
            //- steps.1.2.3
            DesignSurfaceExt2 surface = CreateDesignSurface();
            //- step.4
            //- choose an alignment mode...
            ((DesignSurfaceExt2)surface).UseGridWithoutSnapping(new System.Drawing.Size(16, 16));
            //- step.5
            //- create the Root component, in these cases a Form
            try
            {
                Form rootComponent = null;
                rootComponent = (Form)surface.CreateRootComponent(typeof(Form), new Size(800, 620));
                rootComponent.Text = "Root Component (800x620)";
                rootComponent.BackColor = Color.LightGreen;
                //-
                //-
                //- step.4
                //- display the DesignSurface
                Control view = surface.GetView();
                if (null == view)
                    return;
                //- change some properties
                view.Text = "Test Form N. " + iTabPageSelectedIndex;
                view.Dock = DockStyle.Fill;
                //- Note these assignments
                view.Parent = tp;
            }//end_try
            catch (Exception ex)
            {
                MessageBox.Show(Name + " the DesignSurface N. " + iTabPageSelectedIndex + " has generated errors during loading!Exception: " + ex.Message);
                return;
            }//end_catch
        }

        private void newFormAlignControlByhandMenuItem_Click(object sender, EventArgs e)
        {
            TabPage tp = new TabPage("Design Form (Freeform)");
            this.tabControl1.TabPages.Add(tp);
            int iTabPageSelectedIndex = this.tabControl1.SelectedIndex;
            //- steps.1.2.3
            DesignSurfaceExt2 surface = CreateDesignSurface();
            //- step.4
            //- choose an alignment mode...
            ((DesignSurfaceExt2)surface).UseNoGuides();
            //- step.5
            //- create the Root component, in these cases a Form
            try
            {
                Form rootComponent = null;
                rootComponent = (Form)surface.CreateRootComponent(typeof(Form), new Size(800, 620));
                rootComponent.Text = "Root Component (800x620)";
                rootComponent.BackColor = Color.LightGray;
                //-
                //-
                //- step.4
                //- display the DesignSurface
                Control view = surface.GetView();
                if (null == view)
                    return;
                //- change some properties
                view.Text = "Test Form N. " + iTabPageSelectedIndex;
                view.Dock = DockStyle.Fill;
                //- Note these assignments
                view.Parent = tp;
            }//end_try
            catch (Exception ex)
            {
                MessageBox.Show(Name + " the DesignSurface N. " + iTabPageSelectedIndex + " has generated errors during loading!Exception: " + ex.Message);
                return;
            }//end_catch
        }

        private DesignSurfaceExt2 CreateDesignSurface()
        {
            //- step.0
            //- create a DesignSurface and put it inside a Form in DesignTime
            DesignSurfaceExt2 surface = new DesignSurfaceExt2();
            //-
            //-
            IDesignSurfaceExt2 isurf = (IDesignSurfaceExt2)surface;
            this._listOfDesignSurface.Add(isurf);
            //- step.1
            //- enable the UndoEngines
            isurf.GetUndoEngineExt().Enabled = true;
            //- step.2
            //- try to get a ptr to ISelectionService interface
            //- if we obtain it then hook the SelectionChanged event
            ISelectionService selectionService = (ISelectionService)(isurf.GetIDesignerHost().GetService(typeof(ISelectionService)));
            if (null != selectionService)
                selectionService.SelectionChanged += new System.EventHandler(OnSelectionChanged);
            //- step.3
            //- Select the service IToolboxService
            //- and hook it to our ListBox
            ToolboxServiceImp tbox = isurf.GetIToolboxService() as ToolboxServiceImp;
            if (null != tbox)
                tbox.Toolbox = listBox1;
            //-
            //- finally return the Design surface
            return surface;
        }

        private void SelectRootComponent()
        {
            //- find out the DesignSurfaceExt control hosted by the TabPage
            IDesignSurfaceExt isurf = GetCurrentIDesignSurface();
            if (null != isurf)
                this.propertyGrid1.SelectedObject = isurf.GetIDesignerHost().RootComponent;
        }

        //- When the selection changes this sets the PropertyGrid's selected component
        private void OnSelectionChanged(object sender, System.EventArgs e)
        {
            IDesignSurfaceExt isurf = GetCurrentIDesignSurface();

            if (null != isurf)
            {
                ISelectionService selectionService = null;
                selectionService = isurf.GetIDesignerHost().GetService(typeof(ISelectionService)) as ISelectionService;
                this.propertyGrid1.SelectedObject = selectionService.PrimarySelection;

                resetExtendedPropControls();

                if (selectionService.PrimarySelection == null)
                    return;

                // This is where we handle the XMLFormExtendedTag Properties based on selection change.
                if (((Control)selectionService.PrimarySelection).Tag == null)
                    return;

                if (((Control)selectionService.PrimarySelection).Tag.ToString().Length > 0)
                {
                    XMLFormExtendedTag thisTag = new XMLFormExtendedTag(((Control)selectionService.PrimarySelection).Tag.ToString());
                    if (thisTag.text != null)
                        tbExtendedPropText.Text = thisTag.text;
                    if (thisTag.dataType != null)
                        tbExtendedPropDataType.Text = thisTag.dataType;
                    if (thisTag.outlookID != null)
                        tbExtendedPropOutlookID.Text = thisTag.outlookID;
                    if (thisTag.position > 0)
                        nudExtentedPropPosition.Value = thisTag.position;
                    if (thisTag.required)
                        cbExtendedPropRequired.Checked = true;
                    if (thisTag.requires != null)
                        tbExtendedPropRequires.Text = thisTag.requires;
                }
            }
        }

        private void undoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            IDesignSurfaceExt isurf = GetCurrentIDesignSurface();
            if (null != isurf)
                isurf.GetUndoEngineExt().Undo();
        }

        private void redoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            IDesignSurfaceExt isurf = GetCurrentIDesignSurface();
            if (null != isurf)
                isurf.GetUndoEngineExt().Redo();
        }

        #endregion

        #region XMLPanel Controls (Load, Clear, Etc)

        private void LoadXMLTemplateDesign(string templateFile, IDesignSurfaceExt isurf)
        {
            Control templateWorkArea = null;

            if (null != isurf)
                templateWorkArea = (Control)isurf.GetIDesignerHost().RootComponent;
            else
                return;

            XMLFormTemplate theTemplate = new XMLFormTemplate();

            theTemplate.LoadXMLTemplate(templateFile, templateWorkArea, isurf);
        }

        private void ExtendedPropItem_Click(object sender, EventArgs e)
        {
            if (!panelXMLExtendedTagProps.Enabled)
                return;

            IDesignSurfaceExt isurf = GetCurrentIDesignSurface();

            Control selectedControl = ((Control)this.propertyGrid1.SelectedObject);

            if (!allowedExtendableControls.Contains(selectedControl.GetType().ToString()))
                return;

            if (null != isurf)
            {
                this.UseWaitCursor = true;

                try
                {
                    if (selectedControl.Tag == null)
                    {
                        // Then we need to create the first tag object for the control.
                        selectedControl.Tag = "position:0";
                    }
                    XMLFormExtendedTag thisTag = new XMLFormExtendedTag(selectedControl.Tag.ToString());
                    switch (((Control)sender).Name)
                    {
                        case "tbExtendedPropText": thisTag.text = ((Control)sender).Text; break;
                        case "nudExtentedPropPosition": thisTag.position = Convert.ToInt16(((NumericUpDown)sender).Value); break;
                        case "cbExtendedPropRequired": thisTag.required = ((CheckBox)sender).Checked; break;
                        case "tbExtendedPropRequires": thisTag.requires = ((Control)sender).Text; break;
                        case "tbExtendedPropOutlookID": thisTag.outlookID = ((Control)sender).Text; break;
                        case "tbExtendedPropDataType": thisTag.dataType = ((Control)sender).Text; break;
                    }

                    selectedControl.Tag = thisTag.BuildString();

                    this.UseWaitCursor = false;
                }
                catch
                {
                    MessageBox.Show("Issue editing Extended Properties. Try again.");
                    this.UseWaitCursor = false;
                }
            }
        }

        #endregion

        private void tsbFormListEditor_Click(object sender, EventArgs e)
        {
            ListEditorForm _editorBox = new ListEditorForm();
            if (_editorBox.IsDisposed)
                _editorBox = new ListEditorForm();
            else
                _editorBox.Focus();
            _editorBox.TopMost = true;
            _editorBox.Show();
        }
    }
}
